#include "stdafx.h"
#include "ckModuleManager.h"
#include "ckRunTime.h"
#include "ckError.h"
#include "zModule.h"

#include "ckConnection.h"
#include "ckCommand.h"

namespace ck
{
	ModuleManager::ModuleManager()
	{
		m_pConnection = NULL;
	}


	ModuleManager::~ModuleManager()
	{
	}

	void ModuleManager::SetConnection(Connection* pConnection)
	{
		m_pConnection = pConnection;
	}

	ModuleManager*	ModuleManager::GetInstance()
	{
		static ModuleManager g_ckModuleManager;
		return &g_ckModuleManager;
	}

	RESULTCODE ModuleManager::Load()
	{
		RunTime* pRumTime = RunTime::GetInstance();
		const char* szModHome = pRumTime->GetModuleHome();

		Module* pModule = NULL;

		const char* szSQL = "SELECT ID, CK_NAME, CK_PATH, CK_TIME FROM CK_MODULE";		
		Command* pCommand = m_pConnection->CreateCommand();
		ADODB::_RecordsetPtr pRecordset = pCommand->ExecuteQuery(szSQL);
		if (pRecordset)
		{
			while (!pRecordset->adoEOF)
			{
				_bstr_t bstrName = (_bstr_t)pRecordset->GetCollect("CK_NAME");

				pModule = LoadModule((char*)bstrName);
				if (pModule != NULL)
				{
					m_modules.push_back(pModule);
				}
				pRecordset->MoveNext();
			}
		}

		pCommand->Release();

		return RC_SUCCESS;
	}

	Module*	ModuleManager::LoadModule(const char* szName)
	{
		Module* pModule = NULL;
		RunTime* pRumTime = RunTime::GetInstance();
		const char* szModHome = pRumTime->GetModuleHome();

		char szModName[_MAX_FNAME];
		memset(szModName, 0, _MAX_FNAME);
#ifdef _DEBUG
		sprintf(szModName, "%sD", szName);
#else
		sprintf(szModName, "%s", szName);
#endif
		char szModPath[_MAX_PATH];
		memset(szModPath, 0, _MAX_FNAME);
		_makepath(szModPath, NULL, szModHome, szModName, "dll");
		
		HMODULE handler = ::LoadLibrary(szModPath);
		if (handler == NULL)
		{
			DWORD dw = ::GetLastError();
			LPTSTR errmsg = NULL;
			::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
				FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				dw,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				(LPTSTR)&errmsg,
				0, NULL);

			Error* pError = Error::GetInstance();
			pError->SetError(errmsg);

			::LocalFree(errmsg);
		}
		else
		{
			typedef Module* (*FF)();
			FF fp =  (FF)::GetProcAddress((HINSTANCE)handler, "ckGetCheckModuleInstance");
			if (!fp)
			{
				::FreeLibrary((HINSTANCE)handler);
			}

			pModule = (*fp)();
			pModule->SetHandler(handler);
		}

		return pModule;
	}

	bool ModuleManager::Find(const char* szName)
	{
		if (!szName)
		{
			return false;
		}

		int nCount = 0;

		char szSQL[_MAX_PATH];
		sprintf(szSQL, "SELECT COUNT(*) AS CNT FROM CK_MODULE WHERE CK_NAME='%s'", szName);
		Command* pCommand = m_pConnection->CreateCommand();
		try
		{
			ADODB::_RecordsetPtr pRecordset = pCommand->ExecuteQuery(szSQL);
			if (pRecordset)
			{
				if (!pRecordset->adoEOF)
				{
					nCount = (int)pRecordset->GetCollect("CNT");
				}
			}
		}
		catch (_com_error e)
		{
			TRACE3("%u,%x,%s", e.Error(), e.ErrorMessage(), (char*)e.Description());
		}

		return (nCount > 0);
	}

	z_uint32 ModuleManager::GetCount()
	{
		return m_modules.size();
	}

	Module*	ModuleManager::GetModule(z_uint32 i)
	{
		if (i >= m_modules.size())
		{
			return NULL;
		}
		return m_modules[i];
	}

	Operator* ModuleManager::GetOperator(z_uint32 opcode)
	{
		z_uint32 modcode = (opcode >> 4);

		Module* pModule = GetModuleByCode(modcode);
		if (pModule == NULL)
		{
			return NULL;
		}
		return pModule->GetOperatorByCode(opcode);
	}

	Module* ModuleManager::GetModuleByCode(z_uint32 code)
	{
		Module* pModule = NULL;
		std::vector<Module*>::iterator iter;
		for (iter = m_modules.begin(); iter != m_modules.end(); iter++)
		{
			pModule = *iter;
			if (pModule->GetCode() == code)
			{
				return pModule;
			}
		}
		return NULL;
	}

	RESULTCODE ModuleManager::RegisterModule(const char* szName)
	{
		if (szName == NULL)
		{
			return RC_FAILURE;
		}

		int nCount = 0;
		const char *szPath = "";

		char szSQL[_MAX_PATH];
		sprintf(szSQL, "INSERT INTO CK_MODULE (CK_NAME, CK_PATH, CK_TIME) VALUES('%s','%s',now())", szName, szPath);
		Command* pCommand = m_pConnection->CreateCommand();
		return m_pConnection->Execute(szSQL);
	}
}

